package com.zhxh.nzpos.utils;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Point;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.os.Environment;
import android.os.StatFs;
import android.view.View;
import android.view.Window;

public class AndroidUtils {

	private static String mSQLiteVersion = null;
	private static Boolean mSQLiteSupportsFTS3 = null;
	private static Boolean mSQLiteSupportsFTS4 = null;
	private static Boolean mSQLiteSupportsForeignKeys = null;
	private static Rect mStatusBarRect = new Rect();
	private static int [] mLocation = new int [2];
	/**
	 * Get free (unused) space on external storage.<br>
	 * <br>
	 * See {@link Environment#getExternalStorageDirectory()}.
	 * 
	 * @return free space in kilobytes
	 */
	public static int getFreeExteranlStorageSize() {
		StatFs stats = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
		int availableBlocks = stats.getAvailableBlocks();
		int blockSizeInBytes = stats.getBlockSize();
		
		return availableBlocks * (blockSizeInBytes / 1024);
	}
	
	
	/**
	 * Is device connected to network (WiFi or mobile).<br>
	 * <br>
	 * <b>Hint</b>: A connection to WiFi does not guarantee Internet access.
	 * 
	 * @param context
	 * 
	 * @return {@code true} if device is connected to mobile network or WiFi
	 */
	public static boolean isConnected(Context context) {
		return isWiFiConnected(context) || isMobileNetworkConnected(context);
	}
	
	/**
	 * Is device connected to WiFi?<br>
	 * <br>
	 * <b>Hint</b>: A connection to WiFi does not guarantee Internet access.
	 * 
	 * @param context
	 * 
	 * @return {@code true} if device is connected to an access point
	 */
	public static boolean isWiFiConnected(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		return cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
	}
	
	
	/**
	 * Is device connected to mobile network?
	 * 
	 * @param context
	 * 
	 * @return {@code true} if device is connected to mobile network
	 */
	public static boolean isMobileNetworkConnected(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		return cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected();
	}
	
	
	/**
	 * Get installed SQLite version as string.
	 * 
	 * @return installed SQLite version as string (e.g. {@code "3.5.9"})
	 */
	public static String getSQLiteVersion() {
		if (mSQLiteVersion == null) {
			SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(":memory:", null);
			Cursor cursor = db.rawQuery("select sqlite_version() AS sqlite_version", null);
			
			mSQLiteVersion = "";
			
			while (cursor.moveToNext()) {
				mSQLiteVersion += "." + cursor.getString(0);
			}
			
			if (mSQLiteVersion.startsWith(".")) {
				mSQLiteVersion = mSQLiteVersion.substring(1);
			}
			
			cursor.close();
			db.close();
		}
		
		return mSQLiteVersion;
	}
	
	/**
	 * Does SQLite support FTS3 (full text search)?
	 * 
	 * @return {@code true} if SQLite supports FTS3
	 */
	public static boolean doesSQLiteSupportFTS3() {
		if (mSQLiteSupportsFTS3 == null) {
			mSQLiteSupportsFTS3 = StringUtils.compareVersion(
					".", "3.4.0", getSQLiteVersion()) <= 0;
		}
		
		return mSQLiteSupportsFTS3;
	}
	
	/**
	 * Does SQLite support FTS4 (full text search)?
	 * 
	 * @return {@code true} if SQLite supports FTS4
	 */
	public static boolean doesSQLiteSupportFTS4() {
		if (mSQLiteSupportsFTS4 == null) {
			mSQLiteSupportsFTS4 = StringUtils.compareVersion(
					".", "3.7.4", getSQLiteVersion()) <= 0;
		}
		
		return mSQLiteSupportsFTS4;
	}
	
	/**
	 * Does SQLite support foreign keys?
	 * 
	 * @return {@code true} if SQLite supports foreign keys
	 */
	public static boolean doesSQLiteSupportsForeignKeys() {
		if (mSQLiteSupportsForeignKeys == null) {
			mSQLiteSupportsForeignKeys = StringUtils.compareVersion(
					".", "3.6.19", getSQLiteVersion()) <= 0;
		}
		
		return mSQLiteSupportsForeignKeys;
	}
	
	/**
	 * Get status bar height.<br>
	 * <br>
	 * <b>Note</b>: Call this when content is completely inflated. So {@code onCreate} of an
	 * activity won't work.
	 * 
	 * @param window
	 *            window of application
	 * 
	 * @return height of status bar in pixel
	 */
	public static int getStatusBarHeight(Window window) {
		window.getDecorView().getWindowVisibleDisplayFrame(mStatusBarRect);
		return mStatusBarRect.top;
	}
	
	/**
	 * Get title bar height.<br>
	 * <br>
	 * <b>Note</b>: Call this when content is completely inflated. So {@code onCreate} of an
	 * activity won't work.
	 * 
	 * @param window
	 *            window of application
	 * 
	 * @return height of status bar in pixel
	 */
	public static int getTitleBarHeight(View view) {
		view.getWindowVisibleDisplayFrame(mStatusBarRect);
		return mStatusBarRect.top;
	}
	
	/**
	 * Get offset of application content from top (so status bar + title bar).<br>
	 * <br>
	 * <b>Note</b>: Call this when content is completely inflated. So {@code onCreate} of an
	 * activity won't work.
	 * 
	 * @param view
	 *            any view which is attached to the content
	 * 
	 * @return offset to top in pixel
	 */
	public static int getContentOffsetFromTop(View view) {
		int offset = view.getRootView().findViewById(Window.ID_ANDROID_CONTENT).getTop();
		
		if (offset == 0) {
			view.getWindowVisibleDisplayFrame(mStatusBarRect);
			offset = mStatusBarRect.top;
		}
		
		return offset;
	}
	
	/**
	 * Get location of view relative to screen.<br>
	 * <br>
	 * <b>Note</b>: Call this when content is completely inflated. So {@code onCreate} of an
	 * activity won't work.
	 * 
	 * @param view
	 *            any view which is attached to the content
	 * 
	 * @return location pixel
	 */
	public static Point getScreenLocation(View view) {
		view.getLocationOnScreen(mLocation);
		return new Point(mLocation[0], mLocation[1]);
	}
	
	
	/**
	 * Get location of view relative to application content (so no status bar and title bar).<br>
	 * <br>
	 * <b>Note</b>: Call this when content is completely inflated. So {@code onCreate} of an
	 * activity won't work.
	 * 
	 * @param view
	 *            any view which is attached to the content
	 * 
	 * @return location pixel
	 */
	public static Point getContentLocation(View view) {
		Point point = getScreenLocation(view);
		point.y -= getContentOffsetFromTop(view);
		return point;
	}


}
